// Jeremy Lee
// Space Wars
// In each level, killing 20 enemies will advance you to the next level.

using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
using Microsoft.Xna.Framework.Net;
using Microsoft.Xna.Framework.Storage;

namespace SpaceWars
{
    /// This is the main type for the game
    public class Game1 : Microsoft.Xna.Framework.Game
    {
        GraphicsDeviceManager graphics;
        SpriteBatch spriteBatch;
        Vector2 SCREEN_SIZE = new Vector2(800.0f, 600.0f);
        Stage[] levels = null;
        int currentLevel = 0;
        bool firing = false;
        double fireTrigger = 0.0;
        Random rand = new Random();
        int skipLevel = 0;
        // Sound using XACT
        AudioEngine audio;
        WaveBank wave;
        SoundBank sound;

        public Game1()
        {
            graphics = new GraphicsDeviceManager(this);
            Content.RootDirectory = "Content";
            IsFixedTimeStep = false;
            graphics.PreferredBackBufferWidth = (int)SCREEN_SIZE.X;
            graphics.PreferredBackBufferHeight = (int)SCREEN_SIZE.Y;
            graphics.ApplyChanges();
        }

        protected override void Initialize() { base.Initialize(); }

        protected override void LoadContent()
        {
            //audio = new AudioEngine("Content\\media\\Win\\sounds.xgs");
            //wave = new WaveBank(audio, "Content\\media\\Win\\WaveCollection.xwb");
            //sound = new SoundBank(audio, "Content\\media\\Win\\SoundStaging.xsb");
            //sound.PlayCue("bgMusic");
            levels = new Stage[3];
            spriteBatch = new SpriteBatch(GraphicsDevice);
            Texture2D bgTex = Content.Load<Texture2D>("media\\bg");
            Texture2D shipTex = Content.Load<Texture2D>("media\\ship");
            Texture2D booletTex = Content.Load<Texture2D>("media\\bullet");
            Texture2D enemy1Tex = Content.Load<Texture2D>("media\\enemy1");
            Texture2D enemy2Tex = Content.Load<Texture2D>("media\\enemy2");
            Enemy[] enemyList = new Enemy[50];
            double[] spawnTime = new double[50];
            for (int i = 0; i < 50; i++)
            {
                int tmp = rand.Next( 16, (int)SCREEN_SIZE.Y-16 );
                enemyList[i] = new Enemy(SCREEN_SIZE, enemy1Tex, new Vector2( (float)(tmp%2)*SCREEN_SIZE.X, (float)tmp), 
                                         new Vector2( (float)Math.Sign((double)(tmp%2)-0.5)*-50.0f, 0.0f), 
                                         new Vector2(32.0f), new Vector2(16.0f), (double)tmp%2*Math.PI, false);
                spawnTime[i] = (double)i * 1.0;
            }
            levels[0] = new Stage(SCREEN_SIZE, bgTex, shipTex, booletTex, 100, enemyList, spawnTime);
            enemyList = new Enemy[50];
            spawnTime = new double[50];
            for (int i = 0; i < 50; i++){
                int tmp = rand.Next(360);
                double tmpAngle = (double)tmp / 180.0 * Math.PI;
                Vector2 position = new Vector2((float)Math.Cos(tmpAngle), (float)Math.Sin(tmpAngle));
                Vector2 direction = -position;
                position *= 500.0f;
                position += SCREEN_SIZE / 2.0f;
                direction *= 50.0f;
                enemyList[i] = new Enemy(SCREEN_SIZE, enemy2Tex, position, direction, 
                                         new Vector2(32.0f), new Vector2(16.0f), Math.PI+tmpAngle, false);
                spawnTime[i] = (double)i * 2.0;
            }
            levels[1] = new Stage(SCREEN_SIZE, bgTex, shipTex, booletTex, 100, enemyList, spawnTime);
            for (int i = 0; i < 50; i++){
                int tmp = rand.Next(2);
                enemyList[i] = new Enemy(SCREEN_SIZE, enemy2Tex, new Vector2( SCREEN_SIZE.X, (1.0f + (float)tmp*1.0f)*SCREEN_SIZE.Y/3.0f),
                                         new Vector2( -50.0f, 0.0f), new Vector2(32.0f), new Vector2(16.0f), 0.0, false, 2 );
                spawnTime[i] = (double)i * 1.22;
            }
            levels[2] = new Stage(SCREEN_SIZE, bgTex, shipTex, booletTex, 100, enemyList, spawnTime);
            levels[0].start();
        }

        protected override void UnloadContent() { }

        protected override void Update(GameTime gameTime)
        {
            //audio.Update();
            KeyboardState ks = Keyboard.GetState();
            double elapsedTime = gameTime.ElapsedGameTime.TotalSeconds;

            if (ks.IsKeyDown(Keys.Escape))
                this.Exit();

            PlayerShip ps = levels[currentLevel].playerShip;
            
            if (ps.alive){
                // Movement
                if (currentLevel == 0){
                    // Can only move ship up and down.
                    if (ks.IsKeyDown(Keys.Up))
                        levels[currentLevel].playerShip.vel += new Vector2(0.0f, -50.0f);
                    if (ks.IsKeyDown(Keys.Down))
                        levels[currentLevel].playerShip.vel += new Vector2(0.0f, 50.0f);
                    // Left and right move background.
                    if (ks.IsKeyDown(Keys.Left)){
                        levels[currentLevel].bg.vel += new Vector2(-100.0f, 0.0f);
                        levels[currentLevel].playerShip.angle = Math.PI;
                    }
                    if (ks.IsKeyDown(Keys.Right)){
                        levels[currentLevel].bg.vel += new Vector2(100.0f, 0.0f);
                        levels[currentLevel].playerShip.angle = 0.0;
                    }
                }
                else if (currentLevel == 1){
                    // Can only rotate ship left and right
                    if (ks.IsKeyDown(Keys.Left))
                        levels[currentLevel].playerShip.angle -= Math.PI * elapsedTime;
                    if (ks.IsKeyDown(Keys.Right))
                        levels[currentLevel].playerShip.angle += Math.PI * elapsedTime;
                }
                else{
                    if (ks.IsKeyDown(Keys.Left))
                        levels[currentLevel].playerShip.angle -= Math.PI * elapsedTime;
                    if (ks.IsKeyDown(Keys.Right))
                        levels[currentLevel].playerShip.angle += Math.PI * elapsedTime;
                    Vector2 tmp = new Vector2((float)Math.Cos(ps.angle), (float)Math.Sin(ps.angle));
                    if (ks.IsKeyDown(Keys.Up))
                        levels[currentLevel].playerShip.vel += 50.0f * tmp;
                    if( ks.IsKeyDown(Keys.Down) )
                        levels[currentLevel].playerShip.vel += -50.0f * tmp;
                    levels[currentLevel].bg.vel += levels[currentLevel].playerShip.vel * -0.5f;
                }
                // Firing
                if (fireTrigger > 0.33){
                    fireTrigger = 0.0;
                    firing = false;
                }
                if (ks.IsKeyDown(Keys.Space)){
                    int bulletNum = levels[currentLevel].playerShip.maxBullets - levels[currentLevel].playerShip.bulletsLeft;
                    if (!firing){
                        //sound.PlayCue("shoot");
                        levels[currentLevel].fire();
                        firing = true;
                    }else
                        fireTrigger += elapsedTime;
                }else{
                    firing = false;
                    fireTrigger = 0.0;
                }
            }
            levels[currentLevel].update(elapsedTime, sound);
            if (levels[currentLevel].killCount >= 20 ){
                levels[currentLevel].stop();
                currentLevel++;
                if (currentLevel <= 2)
                    levels[currentLevel].start();
                else
                    currentLevel--;
            }

            if (ks.IsKeyDown(Keys.C)){
                if (skipLevel != -1 && skipLevel < 5){
                    levels[currentLevel].stop();
                    currentLevel++;
                    if (currentLevel <= 2)
                        levels[currentLevel].start();
                    skipLevel = -1;
                }
            }else
                skipLevel = currentLevel + 3;

            base.Update(gameTime);
        }

        protected override void Draw(GameTime gameTime)
        {
            GraphicsDevice.Clear(Color.Black);
            levels[currentLevel].draw(spriteBatch);
            base.Draw(gameTime);
        }
    }
}
